package com.infocollect.common.utils.oss;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Random;

import com.infocollect.common.exception.ResponseException;
import com.infocollect.framework.config.OSSConfig;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PolicyConditions;
import com.aliyun.oss.model.PutObjectResult;


public class OSSClientUtil {

	/** Logger */
	private static final Logger log = LoggerFactory.getLogger(OSSClientUtil.class);

	private OSSClient ossClient;


	private OSSConfig ossConfig;
	private static final String separator = "/";

	public OSSClientUtil(OSSConfig ossConfig) {
		this.setOssConfig(ossConfig);
		ossClient = new OSSClient(ossConfig.getEndpoint(), ossConfig.getAccessKeyId(),
				ossConfig.getAccessKeySecret());
	}

	public void setOssConfig(OSSConfig ossConfig) {
		this.ossConfig = ossConfig;
	}

	/**
	 * 销毁
	 */
	public void destory() {
		ossClient.shutdown();
	}

	/**
	 * 上传图片
	 *
	 * @param url
	 */
	public void uploadImg2Oss(String url) {
		File fileOnServer = new File(url);
		FileInputStream fin;
		try {
			fin = new FileInputStream(fileOnServer);
			String[] split = url.split("/");
			this.uploadFile2OSS(fin, split[split.length - 1]);
		} catch (FileNotFoundException e) {
			throw new ResponseException(5002, "图片上传失败");
		}
	}

	public String uploadImg2Oss(MultipartFile file) {
		if (file.getSize() > 1024 * 1024 * 10) {
			throw new ResponseException(5002, "上传图片大小不能超过10M！");
		}
		String originalFilename = file.getOriginalFilename();
		String substring = originalFilename.substring(originalFilename.lastIndexOf(".")).toLowerCase();
		Random random = new Random();
		String name = random.nextInt(10000) + System.currentTimeMillis() + substring;
		try {
			InputStream inputStream = file.getInputStream();
			this.uploadFile2OSS(inputStream, name);
			return name;
		} catch (Exception e) {
			throw new ResponseException(5002, "图片上传失败");
		}
	}

	/**
	 * 获得图片路径
	 *
	 * @param fileUrl
	 * @return
	 */
	public String getImgUrl(String fileUrl) {
		if (!StringUtils.isEmpty(fileUrl)) {
			String[] split = fileUrl.split("/");
			return this.getUrl(ossConfig.getDirectory() + split[split.length - 1], null);
		}
		return null;
	}
	public String getnbImgUrl(String fileUrl) {
		if (!StringUtils.isEmpty(fileUrl)) {
			String[] split = fileUrl.split("/");
			return this.getUrl(fileUrl, null);
		}
		return null;
	}

	/**
	 * 上传到OSS服务器 如果同名文件会覆盖服务器上的
	 *
	 * @param instream
	 *            文件流
	 * @param fileName
	 *            文件名称 包括后缀名
	 * @return 出错返回"" ,唯一MD5数字签名
	 */
	public String uploadFile2OSS(InputStream instream, String fileName) {
		String ret = "";
		try {
			// 创建上传Object的Metadata
			ObjectMetadata objectMetadata = new ObjectMetadata();
			objectMetadata.setContentLength(instream.available());
			objectMetadata.setCacheControl("no-cache");
			objectMetadata.setHeader("Pragma", "no-cache");
			objectMetadata.setContentType(getcontentType(fileName.substring(fileName.lastIndexOf("."))));
			objectMetadata.setContentDisposition("inline;filename=" + fileName);
			// 上传文件
			PutObjectResult putResult = ossClient.putObject(ossConfig.getBucket(),fileName, instream, objectMetadata);
			ret = putResult.getETag();
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			try {
				if (instream != null) {
					instream.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return ret;
	}

	/**
	 * Description: 判断OSS服务文件上传时文件的contentType
	 *
	 * @param FilenameExtension
	 *            文件后缀
	 * @return String
	 */
	public static String getcontentType(String FilenameExtension) {
		if (FilenameExtension.equalsIgnoreCase("bmp") || FilenameExtension.equalsIgnoreCase(".bmp")) {
			return "image/bmp";
		}
		if (FilenameExtension.equalsIgnoreCase("gif") || FilenameExtension.equalsIgnoreCase(".gif")) {
			return "image/gif";
		}
		if (FilenameExtension.equalsIgnoreCase("jpeg") || FilenameExtension.equalsIgnoreCase("jpg")
				|| FilenameExtension.equalsIgnoreCase("png")) {
			return "image/jpeg";
		}
		if (FilenameExtension.equalsIgnoreCase("html") || FilenameExtension.equalsIgnoreCase(".html")) {
			return "text/html";
		}
		if (FilenameExtension.equalsIgnoreCase("txt") || FilenameExtension.equalsIgnoreCase(".txt")) {
			return "text/plain";
		}
		if (FilenameExtension.equalsIgnoreCase("vsd") || FilenameExtension.equalsIgnoreCase(".vsd")) {
			return "application/vnd.visio";
		}
		if (FilenameExtension.equalsIgnoreCase("pptx") || FilenameExtension.equalsIgnoreCase("ppt") || FilenameExtension.equalsIgnoreCase(".pptx") || FilenameExtension.equalsIgnoreCase(".ppt")) {
			return "application/vnd.ms-powerpoint";
		}
		if (FilenameExtension.equalsIgnoreCase("docx") || FilenameExtension.equalsIgnoreCase("doc") || FilenameExtension.equalsIgnoreCase(".docx") || FilenameExtension.equalsIgnoreCase(".doc")) {
			return "application/msword";
		}
		if (FilenameExtension.equalsIgnoreCase("xml")) {
			return "text/xml";
		}
		if (FilenameExtension.equalsIgnoreCase("pdf") || FilenameExtension.equalsIgnoreCase(".pdf")) {
			return "application/pdf";
		}
		return "image/jpeg";
	}

	/**
	 * 获得url链接
	 *
	 * @param key
	 * @return
	 */
	public String getUrl(String key, Long expireTime) {
		if (expireTime == null)
			expireTime = ossConfig.getExpireFileUrl();
		Date expiration = new Date(new Date().getTime() + 1000 * expireTime);
		// 生成URL
		URL url = ossClient.generatePresignedUrl(ossConfig.getBucket(), key, expiration);
		if (url != null) {
			if ("1".equals(ossConfig.getGcloudFlag())){
				return url.toString().replaceAll(ossConfig.getEndpoint(),ossConfig.getUrlPath());
			}
			else {
				return url.toString();
			}
		}
		return null;
	}
	/**
	 * 获得url链接供后台服务器访问
	 *
	 * @param key
	 * @return
	 */
	public String getUrlForServerUse(String key, Long expireTime) {
		if (expireTime == null)
			expireTime = ossConfig.getExpireFileUrl();
		Date expiration = new Date(new Date().getTime() + 1000 * expireTime);
		// 生成URL
		URL url = ossClient.generatePresignedUrl(ossConfig.getBucket(), key, expiration);
		if (url != null) {
				return url.toString();
		}
		return null;
	}

	/**
	 * 获得签名
	 *
	 * @throws UnsupportedEncodingException
	 *
	 */
	public Map<String, String> getSignature(String filedir) throws UnsupportedEncodingException {
//		final String key = RedisKeyConstant.OSS_SIGNATURE + filedir;
		long expireTime = ossConfig.getExpireSignature();
		long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
		Date expiration = new Date(expireEndTime);
		PolicyConditions policyConds = new PolicyConditions();
		policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
		policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, filedir);

		String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
		byte[] binaryData = postPolicy.getBytes("utf-8");
		String encodedPolicy = BinaryUtil.toBase64String(binaryData);
		String postSignature = ossClient.calculatePostSignature(postPolicy);

		Map<String, String> respMap = new LinkedHashMap<String, String>();
		respMap.put("accessid", ossConfig.getAccessKeyId());
		respMap.put("policy", encodedPolicy);
		respMap.put("signature", postSignature);
		respMap.put("dir", filedir);
		respMap.put("tyCloudFlag", ossConfig.getTyCloudFlag());
		//政务云取urlpath参数,走代理
		if("1".equals(ossConfig.getGcloudFlag()))
		{
			respMap.put("host", ossConfig.getUrlPath());
		}else
		{
			respMap.put("host", "http://" + ossConfig.getBucket() + "." + ossConfig.getEndpoint());
		}


		respMap.put("expire", String.valueOf(expireEndTime / 1000));
//		redisClient.set(RedisKeyPrefix.COMMON, key, respMap, (int) expireTime - 10);
		return respMap;
	}
	/**
	 * 根据文件完整路径删除文件
	 * @param fileUrl
	 */
	public void deleteFileUrl(String fileUrl) {
		ossClient.deleteObject(ossConfig.getBucket(), fileUrl);
	}
	/**
	 * 根据文件名路径获取文件流
	 * @param fileUrl
	 * @return
	 */
	public InputStream getOssObject(String fileUrl) {
		 OSSObject ossObject =ossClient.getObject(ossConfig.getBucket(), fileUrl);
         InputStream inputStream = ossObject.getObjectContent();
		return inputStream;
	}
	public String createFileDir(final String modelType, final String userId) {
		String dir = ossConfig.getDirectory();
		StringBuilder sb = new StringBuilder();
		sb.append(separator);
		if ("image".equals(modelType)) // 图片文件
			sb.append("imageFile");
		else if ("other".equals(modelType)) // 文本文件
			sb.append("otherFile");
		else
			sb.append("otherFile");
		final Date date = new Date();
		SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyMMdd");
		SimpleDateFormat sdf2 = new SimpleDateFormat("HHmmss");
		sb.append(separator).append(sdf1.format(date)).append(separator).append(userId).append(separator)
				.append(sdf2.format(date)).append(separator);
		return dir+sb.toString();
	}
}
